package com.glink.manage.service.scheduled;

import com.glink.common.contants.BaseCodeConstants;
import com.glink.common.util.BaseCommonUtils;
import com.glink.manage.common.enums.AiCodeDict;
import com.glink.manage.common.enums.TaskEnum;
import com.glink.manage.config.ThreadPoolConfig;
import com.glink.manage.domain.SilentResultBean;
import com.glink.manage.domain.SilentResultDetailBean;
import com.glink.manage.ftp.FTPUtils;
import com.glink.manage.service.AiService;
import com.glink.manage.service.SilentResultService;
import com.glink.manage.vo.ai.AiVO;
import com.glink.manage.vo.ai.ResultDetailVO;
import com.glink.manage.vo.ai.ResultValueVO;
import com.glink.manage.vo.silentresult.SilentResultAnalysisSignalVO;
import com.glink.manage.vo.silentresult.SilentResultAnalysisVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Base64;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : qiushaoshan
 * @create 2025/1/21 15:22
 */
@Slf4j
public class AnalysisActuator extends Thread{

    private final PriorityBlockingQueue<SilentResultAnalysisSignalVO> taskSignalQueue;
    
    private final SilentResultService silentResultService;
    
    private final FTPUtils ftpUtils;
    
    private final AiService aiService;

    @Resource
    private ThreadPoolConfig threadPoolConfig;
    
    public AnalysisActuator(SilentResultService silentResultService, FTPUtils ftpUtils, AiService aiService){
        taskSignalQueue = new PriorityBlockingQueue<>();
        this.silentResultService = silentResultService;
        this.ftpUtils = ftpUtils;
        this.aiService = aiService;
    }
    
    public void run() {
        while (true) {
            try {
                SilentResultAnalysisSignalVO analysisVO = this.taskSignalQueue.poll(4L, TimeUnit.SECONDS);
                if (analysisVO != null) {
                    log.info("开始处理的信号量为:{}", analysisVO);
                    String signalAction = analysisVO.getAction();
                    if (TaskEnum.SignalAction.START_TASK.getCode().equals(signalAction)) {
                        log.info("任务启动:{}", analysisVO);
                        ThreadPoolExecutor pool = threadPoolConfig.myThreadPoolExecutor();
                        pool.execute(() -> analysisImage(analysisVO.getObjId(), analysisVO.getFilePath()));
                    }else if (TaskEnum.SignalAction.LOAD_START_UP.getCode().equals(signalAction)) {
                        log.info("初始化:{}", analysisVO);
                        LocalDateTime taskJoinTime = analysisVO.getTaskJoinTime();
                        List<SilentResultAnalysisVO> analysisVOList = silentResultService.findAllToBeAnalyzedByCreateTimeLe(taskJoinTime);
                        if(CollectionUtils.isNotEmpty(analysisVOList)){
                            analysisVOList.forEach(this::addStartTaskSignal);   
                        }
                    }
                }
            } catch (Exception ex) {
                log.error("开始处理信号量出现异常了:{}", ex.getMessage(), ex);
            }
        }
    }

    /**
     * 分析图片
     * @param filePath
     */
    private void analysisImage(String analysisId, String filePath){
        boolean analysisStatus = false;
        String analysisFilePath = "";
        // 结果内容
        String violationContent = "";
        // 状态，0失败，1成功-有异常，2成功，3，其它
        String analysisStatusStr = "";
        
        // 识别类型列表
        List<String> violationTypeList = Lists.newArrayList();
        // 分析时间
        Date analysisTime = new Date();
        
        SilentResultBean silentResultBean = silentResultService.getById(analysisId);
        if(Objects.isNull(silentResultBean) || StringUtils.isBlank(filePath)){
            log.info("获取结果数据失败，analysisId:{}, filePath:{}", analysisId, filePath);
            return;
        }
        List<SilentResultDetailBean> detailBeanList = Lists.newArrayList();
        try {
            
            byte[] ftpFileByte = ftpUtils.getFtpFileByte(filePath);
            if(Objects.nonNull(ftpFileByte) && ftpFileByte.length > 0){
                String base64String = Base64.getEncoder().encodeToString(ftpFileByte);

                AiVO aiVO = aiService.invokeAlgorithm(silentResultBean.getEquipId() + "," + analysisId, base64String);
                if(Objects.nonNull(aiVO) && StringUtils.equals(aiVO.getResultCode(), AiCodeDict.NORMAL.getKey())){
                    log.info("算法分析成功，analysisId：{}", analysisId);
                    // 分析成功
                    analysisStatus = true;
                    
                    ResultValueVO resultValue = aiVO.getResultValue();
                    if(Objects.nonNull(resultValue)){
                     
                        String osdImageData = resultValue.getOsdImageData();
                        if(StringUtils.isNotBlank(osdImageData)){
                            analysisFilePath = FilenameUtils.getFullPath(filePath) + FilenameUtils.getBaseName(filePath) + "_result." + FilenameUtils.getExtension(filePath);

                            boolean status = ftpUtils.uploadFile(analysisFilePath, Base64.getDecoder().decode(osdImageData));
                            if(status){
                                List<String> analyseResults = resultValue.getAnalyseResults();
                                String analyseTime = resultValue.getAnalyseTime();

                                List<ResultDetailVO> resultDetails = resultValue.getResultDetails();
                                if(CollectionUtils.isNotEmpty(resultDetails)){
                                    resultDetails.forEach(resultDetailVO -> {
                                        SilentResultDetailBean silentResultDetailBean = new SilentResultDetailBean();
                                        silentResultDetailBean.setViolationType(resultDetailVO.getAlgCode());
                                        silentResultDetailBean.setViolationContent(resultDetailVO.getResultDesc());
                                        silentResultDetailBean.setBox(resultDetailVO.getResultItems());
                                        silentResultDetailBean.setResultObjId(analysisId);
                                        silentResultDetailBean.setObjId(BaseCommonUtils.generateUUID());
                                        detailBeanList.add(silentResultDetailBean);

                                        if(StringUtils.isNotBlank(resultDetailVO.getAlgCode())){
                                            violationTypeList.add(resultDetailVO.getAlgCode());
                                        }
                                    });
                                }

                                analysisStatusStr = BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode01;
                                try {
                                    analysisTime = BaseCommonUtils.DATE_FORMAT_SECOND_0.parse(analyseTime);
                                }catch (Exception e){
                                    log.error("获取结果数据", e);
                                }

                                silentResultBean.setAnalysisFilePath(analysisFilePath);
                                if(CollectionUtils.isNotEmpty(analyseResults)){
                                    violationContent = String.join(",", analyseResults);
                                }
                            }
                        }else{
                            if(CollectionUtils.isEmpty(resultValue.getAnalyseResults())){
                                analysisStatusStr = "2";
                                violationContent = "成功";
                                log.debug("算法分析，分析结果成功,aiVO:{}", aiVO);
                            }else{
                                analysisStatusStr = "4";
                                violationContent = "图片数据不存在";
                                log.debug("算法分析，图片数据不存在，aiVO：{}", aiVO);    
                            }
                        }
                    }else{
                        analysisStatusStr = "2";
                        violationContent = "成功";
                        log.debug("算法分析，分析结果成功,aiVO:{}", aiVO);
                    }
                }else if(Objects.nonNull(aiVO) && StringUtils.equals(aiVO.getResultCode(), AiCodeDict.REPEAT.getKey())){
                    // 分析成功
                    analysisStatus = true;
                    analysisStatusStr = "3";
                    violationContent = AiCodeDict.REPEAT.getVal();
                }else{
                    if(Objects.nonNull(aiVO)){
                        log.error("算法分析，分析失败：{}", aiVO);
                    }
                    violationContent = "算法分析失败";
                }
            }else{
                violationContent = "获取文件失败";
            }
            
            if(!analysisStatus){
                analysisStatusStr = BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02;
                analysisTime = new Date();
            }
            
            if(StringUtils.isBlank(analysisStatusStr)){
                analysisStatusStr = "3";
                violationContent = "未知";
            }

            silentResultBean.setAnalysisTime(analysisTime);
            silentResultBean.setAnalysisStatus(analysisStatusStr);
            silentResultBean.setViolationContentInit(violationContent);
            silentResultBean.setViolationTypeList(String.join(",", violationTypeList));

            silentResultService.saveAndDetail(silentResultBean, detailBeanList);
        }catch (Exception e){
            log.error("算法分析失败", e);
        }
    }
    
    public void addStartTaskSignal(SilentResultAnalysisVO taskActuatorVO) {
        try {
            SilentResultAnalysisSignalVO signalVO = new SilentResultAnalysisSignalVO();
            BeanUtils.copyProperties(taskActuatorVO, signalVO);
            signalVO.setTaskJoinTime(LocalDateTime.now());
            signalVO.setOrder(10);
            signalVO.setAction(TaskEnum.SignalAction.START_TASK.getCode());
            log.info("添加任务启动信号量到队列中:{}", signalVO);
            this.taskSignalQueue.offer(signalVO);
        } catch (Exception e) {
            log.error("添加到时间自启任务启动信号量到队列中失败:{}", e.getMessage(), e);
        }
    }

    public void startAnalysisOnStartUp(LocalDateTime localDateTime) {
        try {
            SilentResultAnalysisSignalVO signalVO = new SilentResultAnalysisSignalVO();
            signalVO.setTaskJoinTime(localDateTime);
            signalVO.setOrder(10);
            signalVO.setAction(TaskEnum.SignalAction.LOAD_START_UP.getCode());
            log.info("添加任务启动信号量到队列中:{}", signalVO);
            this.taskSignalQueue.offer(signalVO);
        } catch (Exception e) {
            log.error("添加到时间自启任务启动信号量到队列中失败:{}", e.getMessage(), e);
        }
    }
}
